package utils

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/go-playground/validator/v10"
	"github.com/google/uuid"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// GetValidMsg 获取自定义错误消息
func GetValidMsg(err error, obj any) string {
	getOjb := reflect.TypeOf(obj)
	if errs, ok := err.(validator.ValidationErrors); ok {
		for _, e := range errs {
			if f, exist := getOjb.Elem().FieldByName(e.Field()); exist {
				return f.Tag.Get("msg")
			}
		}
	}
	return err.Error()
}

// GetUUID 获取uuid
func GetUUID() string {
	return strings.Replace(uuid.New().String(), "-", "", -1)
}

// RandomSalt 默认随机生成5位字符串
func RandomSalt(num int) string {
	if num < 5 {
		num = 5
	}
	var letters = []byte("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
	salt := make([]byte, num)
	time.Sleep(1)
	rand.Seed(time.Now().UnixNano())
	for i := range salt {
		salt[i] = letters[rand.Intn(len(letters))]
	}
	return string(salt)
}

// GenPassword 生成用户密码
func GenPassword(salt string, password string) string {
	sourceStr := password + salt + password
	return fmt.Sprintf("%x", md5.Sum([]byte(sourceStr)))
}

// GenAppKey 生成app key 32位
func GenAppKey() string {
	sourceStr := RandomSalt(10) + GetUUID() + RandomSalt(4)
	return Gen32BitMD5Encode(sourceStr)
}

// GenSecretKey 生成secret key 32位
func GenSecretKey(label string) string {
	sourceStr := label + GenAppKey() + RandomSalt(21)
	return Gen32BitMD5Encode(RandomSalt(11) + sourceStr)
}

// GenCompanyFilePath 生成公司路径
func GenCompanyFilePath(label string) string {
	sourceStr := label + RandomSalt(8) + strconv.FormatInt(time.Now().Unix(), 10)
	return fmt.Sprintf("%x", md5.Sum([]byte(sourceStr)))
}

// Gen32BitMD5Encode 生成32位md5
func Gen32BitMD5Encode(data string) string {
	h := md5.New()
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

// FormatFileSize 字节的单位转换 保留两位小数
func FormatFileSize(fileSize int64) (size string) {
	if fileSize < 2<<9 {
		//return strconv.FormatInt(fileSize, 10) + "B"
		return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1))
	} else if fileSize < 2<<19 {
		return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(2<<9))
	} else if fileSize < 2<<29 {
		return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(2<<19))
	} else if fileSize < 2<<39 {
		return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(2<<29))
	} else if fileSize < (2 << 49) {
		return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(2<<39))
	} else {
		return fmt.Sprintf("%.2fPB", float64(fileSize)/float64(2<<49))
	}
}
